package org.code.chenwei.day01.ThreadPool;


import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * @BelongsProject: learn-learning-everyday
 * @BelongsPackage: org.chenwei.day01.ThreadPool
 * @Author: Chen Wei
 * @CreateTime: 2024-01-11  09:39
 * @Description: TODO
 * @Version: 1.0
 */
@SuppressWarnings("all")
@Slf4j
public class ThreadPoolDemo {


    //处理十万个线程  18秒
    @Test
    public void threadDemo() throws InterruptedException {
        Long start = System.currentTimeMillis();
        final Random random = new Random();
        final List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            Thread thread = new Thread(() -> {
                list.add(random.nextInt());
            });
            thread.start();
            thread.join();
        }
        long end = System.currentTimeMillis();
        log.info("耗费时间：{}", end - start);
    }

    //线程池处理 0.5秒
    @Test
    public void threadPoolDemo() throws InterruptedException {
        Long start = System.currentTimeMillis();
        final Random random = new Random();
        final List<Integer> list = new ArrayList<>();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 100000; i++) {
            executorService.execute(() -> {
                list.add(random.nextInt());
            });

        }
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.DAYS);
        long end = System.currentTimeMillis();
        log.info("{}", list.size());
        log.info("耗费时间：{}", end - start);
    }

    @Test
    public void threadPoolDemo1() throws InterruptedException {
        //创建固定大小线程池
//        ExecutorService executorService = Executors.newFixedThreadPool(8);
        //创建单线程池
//        ExecutorService executorService = Executors.newSingleThreadExecutor();

        //带缓存线程池 动态创建线程
        ExecutorService executorService = Executors.newCachedThreadPool();

        //定时任务线程池
//        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
        try {

            for (int i = 0; i < 100; i++) {
                int finalI = i;
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        log.info("处理业务:{}", finalI);
                    }
                });
                //定时执行
/*                executorService.schedule(new Runnable() {
                    @Override
                    public void run() {
                        log.info("处理业务:{}", finalI);
                    }
                },5,TimeUnit.SECONDS);*/
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //不会立马关闭线程池，会等待队列中任务执行完成
//            executorService.shutdown();

            //只会等待当前执行的任务执行完
            executorService.shutdownNow();
            //等待线程结束
            executorService.awaitTermination(1, TimeUnit.MINUTES);

            log.info("线程池关闭:{}", executorService.isTerminated());
        }


    }

    //execute 没有返回值
    //submit 有返回值 为future
    @Test
    public void submitThreadPool() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        Future<Integer> future = executorService.submit(() -> {
            log.info("处理业务");
            return 5;
        });
        Integer integer = future.get();
        log.info("结果:{}", integer);


    }
    /*
     * @description:自定义线程池
     * @author: Chen Wei
     * @date: 2024年1月11日, 0011 15:52
     * @param: []
     * @return: void
     *
     * 拒绝策略
     * 1.new ThreadPoolExecutor.AbortPolicy()  丢弃不能接受的任务 并抛出异常
     * 2.new ThreadPoolExecutor.CallerRunsPolicy() 在调用threadPoolExecutor.execte()的线程中 直接运行被拒绝的任务
     * 3.new ThreadPoolExecutor.DiscardOldestPolicy() 丢弃阻塞队列最早的任务,将被拒绝的任务放在阻塞队列的最前面，然后重试execte
     * 4.new ThreadPoolExecutor.DiscardPolicy() 直接丢弃不能处理的任务，并且不抛出异常
     **/
    @Test
    public void defineSelfThreadPool() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8,
                16, 0L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(8),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        class DefineSelfThreadPoolTask implements Runnable{
            int i=0;
            public DefineSelfThreadPoolTask(int i){
                this.i=i;
            }
            @Override
            public void run() {
            log.info("线程:{} 正在处理业务:{}",Thread.currentThread().getName(),i);
                try {
                    Thread.sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }


        try {
            for (int i = 1; i <= 100; i++) {
                DefineSelfThreadPoolTask defineSelfThreadPoolTask = new DefineSelfThreadPoolTask(i);
                threadPoolExecutor.execute(defineSelfThreadPoolTask);
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();
            threadPoolExecutor.shutdownNow();

            try {
                threadPoolExecutor.awaitTermination(1,TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /*
     * @description:自定义线程池
     * @author: Chen Wei
     * @date: 2024年1月11日, 0011 15:52
     * @param: []
     * @return: void
     *
     * 线程池淘汰策略
     * 1.正常结束
     * 2.线程异常 线程捕捉到异常后设置completedAbruptly为false，会重新建一个线程，因为是线程是异常结束
     * 3.线程池关闭 分为shutdown 和  shutdownNow
     * shutdown：发送信号，提示线程池关闭，但是线程池不会立即关闭，会等所有任务都执行完毕后关闭
     * shutdownNow：修改线程池状态为STOP 不再接收任务提交 尝试中断线程池中所有的线程（包括正在执行的线程）返回正在等待执行的任务列表 List<Runnable>
       是否会中断当前执行任务，这得看正常执行的任务是否会响应中断
     **/
    @Test
    public void threadPoolEliminationStrategy() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8,
                16, 0L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(8),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        class DefineSelfThreadPoolTask implements Runnable{
            int i=0;
            public DefineSelfThreadPoolTask(int i){
                this.i=i;
            }
            @Override
            public void run() {
            log.info("线程:{} 正在处理业务:{}",Thread.currentThread().getName(),i);
                try {
                    Thread.sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }


        try {
            for (int i = 1; i <= 100; i++) {
                DefineSelfThreadPoolTask defineSelfThreadPoolTask = new DefineSelfThreadPoolTask(i);
                threadPoolExecutor.execute(defineSelfThreadPoolTask);
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();
            threadPoolExecutor.shutdownNow();

            try {
                threadPoolExecutor.awaitTermination(1,TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        System.out.println((-1 << 29));
        System.out.println((-1 << 29) | 0);

    }
}
